std::upper_bound & std::lower_bound
Returns an iterator pointing to the first element in a range gfg ref
upper_bound(first, last, value_to_search_for) lower_bound(first, last, value_to_search_for)
lower_bound: find the first pos in which val could be inserted without changing the order
upper_bound: find last postion in which val could be inserted without changing the order